package com.google.zxing.client.homework;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.zxing.Result;
import com.google.zxing.client.homework.HomeworkInfo;
import com.google.zxing.client.homework.QuestionInfo;
import com.google.zxing.client.homework.utils.Constants;
import com.google.zxing.client.homework.utils.GetQrcodeClientRequestVo;
import com.google.zxing.client.homework.utils.GetQrcodeClientResultVo;
import com.google.zxing.client.homework.utils.NetHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import java.util.Vector;

import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.entity.StringEntity;
import cz.msebera.android.httpclient.protocol.HTTP;


/**
 * Created by yanmaoshen on 2017/11/15.
 */
public class DecodeStringInBarcode {
    /*
画布: 1514 * 2141 pixel   纸张：a4 210mm * 297mm  1mm = 7.2pixel
二维码：
LT： T: 2    L: 1272  B: 46   R: 1316  C: 1294 24
LB： T: 197  L: 1272  B: 241  R: 1316  C: 1294 219
RT： T: 2    L: 1467  B: 46   R: 1511  C: 1488 24
特征区域：
LT： T: 186  L: 8     B: 241  R: 63    C: 36 214
LB： T: 2078 L: 8     B: 2133 R: 241   C: 36 2106
RB： T: 2078 L: 1452  B: 2133 R: 1507  C: 1480 2106
答题区：T: 246 L: 4 B: 2066 R: 1512
选项：   L :  28-4    W：42  （70-28）
cloumn: W :  754    H: 1820     （2066-246）
    * */

    private static final String TAG = "DecodeStringInBarcode";
    //mzzH1IzzrdWzcXcwpzzzGKZzG?jzzzduldG?jzzzdulhx?jz  mzzH1IzzrdWzzzzcwcXpzzGKZzG?jGhzzzzduldG?jh?jhGG!Gzzdulfx?jz，这个是带h5的，顺便解决了
    private static final String testStr = "mzzzzjzzzzjzj-zcZ5cPjw_hgWzRPPPPw_hgIz3PPPPw_hg8jB__E_w_hg_m5PPPPw_hgxGdPPPPw_hgUGUPPPP";
            //"mzzH1IzzrdWzzzzcwcXpzzGKZzG?jGhzzzzduldG?jh?jhGG!Gzzdulfx?jz";

    //code support negative value,but we won't find negative value in correct barcode string, so there is no char '-' in Digs
    private static final String Digs = "zjpcZPqldmGv4nbTheRrH1AafsQNu5JCoV0BOL9I6X2gE_kyW8xUtw=F3KiD7YMS?!-";
    private static final int MaxNumInChar = 64;//max num in one char
    private float PixelsInMM = 7.2f;//max num in one char

    private Vector<Integer> resultVec = new Vector<Integer>();
    private HomeworkInfo homework = null;
    private Context mContext;

    public DecodeStringInBarcode(Context context, String str, float scale) throws NullPointerException{
        mContext = context;
        if (scale != 1.0f){
            PixelsInMM *= scale;
        }
        homework = new HomeworkInfo(scale);

        if (str==null || str.length()==0){
            DecodeString();
        }else if(str.compareTo("test") == 0) {
            setTestInfo();
        }else{
            getHomeworkInfoByID(Integer.parseInt(str));
        }
    }
    private void DecodeString() {
        DecodeString(testStr);
    }

    private void DecodeString( String str){
        resultVec.clear();
        for(int i = 0; i < str.length(); i++) {
            int serial = Digs.indexOf(str.charAt(i));
            if (serial == -1){
                Log.d(TAG, "Found error char in barcode string " + i + " " + str.charAt(i));
            }
            if (serial != MaxNumInChar+2) { // note there , ignore nagitive sign there
                resultVec.add(new Integer(serial));
            }
        }
        if(resultVec.size() <= 5){
            homework.setHomeworkOrWrongBookID(getNumber(0, resultVec.size(), false));
            getHomeworkInfoByID(homework.getHomeworkOrWrongBookID());
        }else {
            setInfo();
            printInfo();
        }
    }

    private void getHomeworkInfoByID(long id){

        final GetQrcodeClientRequestVo getQrcodeRequst = new GetQrcodeClientRequestVo();
        getQrcodeRequst.setQrID(id);
        getQrcodeRequst.setHeader(7623,
                "3.1.1",
                "iPhoneStudent",
                "1c69f194bc9411e79c6600163e061c25",
                "DE2B81FF-63A2-4086-B9EC-5BF50466DA68;iPhone 6 Plus;iOS10.0.1");

        Gson gson = new Gson();
        String requst_json = gson.toJson(getQrcodeRequst);
        Log.d("login", "用户名密码登录json request=======" + requst_json);

        StringEntity params = new StringEntity(requst_json, HTTP.UTF_8);
        NetHttpClient.post(mContext, Constants.HTTP_GET_QRCODE,
                params, new AsyncHttpResponseHandler() {

                    @Override
                    public void onStart() {
                        super.onStart();
                    }

                    @Override
                    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                        String response = new String(responseBody);
                        Log.d("login", "用户名密码登录json result=======" + response);
                        if (TextUtils.isEmpty(response)) {
                            Toast.makeText(mContext,
                                    "post empty",
                                    Toast.LENGTH_LONG).show();
                        } else {
                            Gson gson = new Gson();
                            GetQrcodeClientResultVo getQrcodeResult = gson.fromJson(
                                    response, GetQrcodeClientResultVo.class);
                            if (getQrcodeResult.getResponseHeader().getSuccessful()) {
                                String info = getQrcodeResult.getInfo();
                                DecodeString(info);
                            } else {
                                Toast.makeText(mContext,
                                        getQrcodeResult.getResponseHeader().getMsg(),
                                        Toast.LENGTH_LONG).show();
                            }
                        }
                    }

                    @Override
                    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                        Toast.makeText(mContext, "server error",
                                Toast.LENGTH_LONG);
                        error.printStackTrace();
                    }

                    @Override
                    public void onFinish() {
                        super.onFinish();
                    }

                });
    }

    private void printInfo(){
        if (checkInfo(homework.getVersion())){
            Log.d(TAG, "printInfo Version : "+homework.getVersion());
        }
        if (checkInfo(homework.getType())){
            Log.d(TAG, "printInfo Type : "+homework.getType());
        }
        if (checkInfo(homework.getHomeworkOrWrongBookID())){
            Log.d(TAG, "printInfo HomeworkOrWrongBookID : "+homework.getHomeworkOrWrongBookID());
        }
        if (checkInfo(homework.getStudentID())){
            Log.d(TAG, "printInfo StudentID : "+homework.getStudentID());
        }
        if (checkInfo(homework.getOutter_t())&&checkInfo(homework.getOutter_l())&&
                checkInfo(homework.getOutter_b())&&checkInfo(homework.getOutter_r())){
            Log.d(TAG, "printInfo Outter : "+homework.getOutter_t() +" " + homework.getOutter_l()
                    +" " + homework.getOutter_b() +" " + homework.getOutter_r());
        }
        if (checkInfo(homework.getPN())){
            Log.d(TAG, "printInfo PN : "+homework.getPN());
        }
        for (int i=0; i<homework.getQuestionList().size(); i++){
            QuestionInfo qInfo = homework.getQuestionList().get(i);
            if (checkInfo(qInfo.getQI())){
                Log.d(TAG, "printInfo question serial:" + i + " qInfo.getQI() : "+qInfo.getQI());
            }
            if (checkInfo(qInfo.getQT())){
                Log.d(TAG, "printInfo question serial:" + i + " qInfo.getQT() : "+qInfo.getQT());
            }
            if (checkInfo(qInfo.getColumn())){
                Log.d(TAG, "printInfo question serial:" + i + " qInfo.getColumn() : "+qInfo.getColumn());
            }
            if (checkInfo(qInfo.getTop())){
                Log.d(TAG, "printInfo question serial:" + i + " qInfo.getTop() : "+qInfo.getTop());
            }
            Vector<Integer> heightVec = qInfo.getHeightVec();
            for (int j=0; j<heightVec.size(); j++){
                if (checkInfo(heightVec.get(j))){
                    Log.d(TAG, "printInfo question serial:" + i + " heightVec serial:" + j + " H:" +heightVec.get(j));
                }
            }
        }
    }

    private boolean checkInfo( long data ){
        if ( data == -1){
            Log.e(TAG, "checkInfo data error : equal -1");
            return false;
        }else {
            return true;
        }
    }

    private int setInfo(){
        int resultLength = resultVec.size();
        if (resultLength < 40){ // base info need 19 numbers
            return -1;
        }

        for (int i=0; i<resultLength; i++){
            if (resultVec.get(i)<0 || resultVec.get(i)>=Digs.length()){
                return -1;
            }
        }

        int serial = 0;
        homework.setVersion(resultVec.get(serial) / 8);
        homework.setType(resultVec.get(serial) % 8);
        serial ++;// 1

        homework.setHomeworkOrWrongBookID(getNumber(serial, 5, false));
        serial += 5; // 6

        homework.setStudentID(getNumber(serial, 5, false));
        serial += 5; // 11

        homework.setClassID(getNumber(serial, 5, false));
        serial += 5; // 16

        homework.setOutter_t((int) getNumber(serial, 2, true) );
        serial += 2;
        homework.setOutter_l( (int)getNumber(serial, 2, true) );
        serial += 2;
        homework.setOutter_b( (int)getNumber(serial, 2, true) );
        serial += 2;
        homework.setOutter_r( (int)getNumber(serial, 2, true) );
        serial += 2; // 19+5
        homework.setPN( (int)getNumber(serial, 1, false) );
        serial += 1;// 20+5

        homework.setLeft1( (int)getNumber(serial, 2, true) );
        serial += 2;// 27
        homework.setLeft2( (int)getNumber(serial, 2, true) );
        serial += 2;// 29
        homework.setOptionWidth( (int)getNumber(serial, 1, true) );
        serial += 1;// 30

        homework.setInner_t( (int)getNumber(serial, 2, true) );
        serial += 2;// 32
        homework.setInner_l( (int)getNumber(serial, 2, true) );
        serial += 2;// 34
        homework.setInner_b( (int)getNumber(serial, 2, true) );
        serial += 2;// 36
        homework.setInner_r( (int)getNumber(serial, 2, true) );
        serial += 2;// 38

        homework.setNotOptionWidth( (homework.getInner_r()-homework.getInner_l())/2 );

        int W1W2= (int)getNumber(serial, 2, true);
        homework.setW1(W1W2/64);
        homework.setW2(W1W2%64);
        serial += 2;// 40

        // ? : MaxNumInChar      ! : MaxNumInChar +1
        //optionSerial means step: -2 —— is new question, need ID, -1—— need QT column top, 0-3 —— need height, >4 —— need '!'
        int optionSerial = -2;
        homework.getQuestionList().clear();
        int qNum = -1;
        for (int i=serial; i<resultLength; ){
            if (optionSerial == -2) {
                homework.addQuestion(new QuestionInfo());
                qNum ++;
                homework.getQuestionList().get(qNum).getHeightVec().clear();
                homework.getQuestionList().get(qNum).setQI( getNumber(i, 5, false) );
                i += 5;
                optionSerial ++;
                continue;
            }
            // QT   column top
            if ( optionSerial == -1 ){
                int QT_column_top = (int)getNumber(i,2, false);
                i += 2;
                homework.getQuestionList().get(qNum).setQT(QT_column_top/1024 );
                homework.getQuestionList().get(qNum).setColumn((QT_column_top % 1024)/512 );
                homework.getQuestionList().get(qNum).setTop(  QT_column_top%512  );//表示有多少个独立区域(n)
                optionSerial ++;
                continue;
            }

            int questionType = homework.getQuestionList().get(qNum).getQT();
            int zoneNum = homework.getQuestionList().get(qNum).getTop();
            if (questionType==0 || questionType==2){ //选择题，其中2代表分列
                for (int j=0; j<zoneNum; j++){
                    homework.getQuestionList().get(qNum).addHeight((int)getNumber(i, 3, true));
                    i += 3;
                    if (i>=resultLength-1){
                        break;
                    }
                }
            }else {//1，3 ，填空解答，3代表分列            // h1- h4 h5……
                int tempNum = (int)getNumber(i, 1, true);
                i++;
                if (tempNum==MaxNumInChar+1) { // !
                    tempNum = (int)getNumber(i, 1, true);
                    i++;
                }
                if (tempNum==MaxNumInChar){
                    tempNum = (int)getNumber(i, 2, true);
                    i += 2;
                }

                if (tempNum > 0) {
                    homework.getQuestionList().get(qNum).addHeight(tempNum);
                }
            }
            optionSerial = -2;

            if (i >= resultLength-1){
                break;
            }
        }


        return 0;
    }

    private long getNumber(int start, int length, boolean isPixels){
        if ( !checkVector(start, length) ){
            return -1;
        }

        long num = 0;
        for (int i=0; i<length; i++){
            num *= MaxNumInChar;
            num += resultVec.get(start+i);
        }
        return (long)(num*(isPixels ? PixelsInMM : 1.0f));
    }

    private boolean checkVector( int start, int length ){
        if (resultVec.size() >= start+length){
            return true;
        }else {
            Log.e(TAG, "DecodeStringInBarcode data error");
            return false;
        }
    }

    public static String getTAG() {
        return TAG;
    }

    public static String getTestStr() {
        return testStr;
    }

    public static String getDigs() {
        return Digs;
    }

    public static int getMaxNumInChar() {
        return MaxNumInChar;
    }

    public Vector<Integer> getResultVec() {
        return resultVec;
    }

    public void setResultVec(Vector<Integer> resultVec) {
        this.resultVec = resultVec;
    }


    private void setTestInfo(){
        homework.setVersion(1);
        homework.setType(1);
        homework.setHomeworkOrWrongBookID(1);
        homework.setStudentID(1);
        homework.setOutter_t(98);
        homework.setOutter_l(8);//22
        homework.setOutter_b(783);
        homework.setOutter_r(556);//543
        homework.setPN(1);
        homework.setCH(766);

        QuestionInfo qInfo1 = new QuestionInfo();
        qInfo1.setQI(1);
        qInfo1.setQT(1);
        qInfo1.setColumn(1);
        qInfo1.setTop(157);
        qInfo1.addHeight(39);
        qInfo1.addHeight(19);
        qInfo1.addHeight(23);
        qInfo1.addHeight(19);
        homework.addQuestion(qInfo1);

        QuestionInfo qInfo2 = new QuestionInfo();
        qInfo2.setQI(2);
        qInfo2.setQT(2);
        qInfo2.setColumn(1);
        qInfo2.setTop(274);
        qInfo2.addHeight(126);
        homework.addQuestion(qInfo2);

        QuestionInfo qInfo3 = new QuestionInfo();
        qInfo3.setQI(3);
        qInfo3.setQT(3);
        qInfo3.setColumn(1);
        qInfo3.setTop(502);
        qInfo3.addHeight(236);
        homework.addQuestion(qInfo3);

        QuestionInfo qInfo4 = new QuestionInfo();
        qInfo4.setQI(4);
        qInfo4.setQT(3);
        qInfo4.setColumn(2);
        qInfo4.setTop(184);
        qInfo4.addHeight(214);
        homework.addQuestion(qInfo4);

        QuestionInfo qInfo5 = new QuestionInfo();
        qInfo5.setQI(5);
        qInfo5.setQT(3);
        qInfo5.setColumn(2);
        qInfo5.setTop(502);
        qInfo5.addHeight(236);
        homework.addQuestion(qInfo5);
    }

    public HomeworkInfo getHomework() {
        return homework;
    }
}
